package executeUpdate;

import com.mysql.jdbc.jdbc2.optional.MysqlDataSource;

import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.Scanner;

public class JDBCInsert {
    //用 Java代码 操作 数据库 比如往数据库插入记录
    //往 java107 数据库中的 student表 插入一条记录
    public static void main(String[] args) throws SQLException {
        // 1. 创建一个数据源对象 数据源对象就描述了要访问的数据库是啥,在哪.
        DataSource dataSource = new MysqlDataSource();
        ((MysqlDataSource)dataSource).setURL("jdbc:mysql://127.0.0.1:3306/java107?characterEncoding=utf8&useSSL=false");
        ((MysqlDataSource)dataSource).setUser("root");
        ((MysqlDataSource)dataSource).setPassword("1111");

        // 2. 和服务建立连接
        Connection connection =  dataSource.getConnection();
        //System.out.println(connection);

        // 3.1 构造要执行的 SQL 语句  [构造请求]
        //String sql = "insert into student values(1,'张三')";  // 这样写插入的数据写死了 !!
        //PreparedStatement statement = connection.prepareStatement(sql);


        //3.2  那怎么写得 灵活 呢 ???
        // 使用字符串拼接的方式: 通过 [用户输入] 的方式
        Scanner scanner = new Scanner(System.in);
        System.out.println("请输入要插入的学号: ");
        String id = scanner.next();
        System.out.println("请输入要插入的姓名: ");
        String name = scanner.next();
        //字符串拼接的问题 : 1. 代码乱      2. 不安全, 容易引发 SQL 注入漏洞.
        //因此, 不应该手动进行拼接SQL. 而是应该借助 PreparedStatement 内部提供的SQL拼装机制
        //String sql = "insert into student values("+ id + ",'"+ name + "')";
        //PreparedStatement statement = connection.prepareStatement(sql);

        // 如何借助 PreparedStatement 内部提供的SQL拼装机制 呢 ??
        //使用 ? 作为占位符, 后面会替换成其他的值
        String sql = "insert into student values(?,?)";
        PreparedStatement statement = connection.prepareStatement(sql);
        statement.setString(1,id); //id 替换第一个 ?
        statement.setString(2,name); // name 替换第二个 ?


        // 4. 执行SQL  [发送请求 & 读取响应]
        //执行方法有 两个
        // executeUpdate 对应 插入删除修改 语句. 返回值表示这次 SQL 影响到的行数. 返回一个 整数
        // executeQuery  对应 查询语句. 返回值是则是返回的临时表数据
        int n = statement.executeUpdate();
        System.out.println("have "+ n + " row affected"); //返回值表示这次 SQL 影响到的行数

        // 5. 完成之后, 就需要关闭释放资源.
        // 释放资源的顺序要和申请资源的顺序正好相反 !!!
        //先创建的后释放, 后创建的先释放 !!!
        statement.close();
        connection.close();
    }
}
